package com.ai.driver.service.impl;

/**
 * ClassName:    DriverBehaviorServiceImpl
 * Description:  TODO
 * Author:       yuzx
 * Date:         2025/9/9 11:21
 * Version:      1.0
 **/


import com.ai.common.core.domain.AjaxResult;
import com.ai.common.utils.StringUtils;
import com.ai.driver.domain.dto.DriverBehaviorRequest;
import com.ai.driver.domain.vo.DriverBehaviorResponse;
import com.ai.driver.service.IDriverBehaviorService;
import com.ai.bd_util.BaiduAuthUtil;
import com.ai.bd_util.BaiduAipUtil;
import okhttp3.*;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * 驾驶行为分析服务实现类（无DAO层，直接返回分析结果）
 */
@Service
public class DriverBehaviorServiceImpl implements IDriverBehaviorService {
    private static final Logger log = LoggerFactory.getLogger(DriverBehaviorServiceImpl.class);

    // 百度驾驶行为分析API配置
    @Value("${baidu.ai.driver.api-url}")
    private String driverApiUrl;
    @Value("${baidu.ai.driver.max-size}")
    private long maxImageSize;
    @Value("${baidu.ai.driver.default-wheel-location}")
    private String defaultWheelLocation;

    // 复用手势识别的鉴权工具类
    @Resource
    private BaiduAuthUtil baiduAuthUtil;

    // OkHttp客户端（与手势识别保持一致）
    private OkHttpClient httpClient;

    /**
     * 初始化OkHttp（Bean创建后自动执行）
     */
    @PostConstruct
    public void initOkHttpClient() {
        this.httpClient = new OkHttpClient().newBuilder().build();
        log.info("驾驶行为分析：OkHttp客户端初始化完成");
    }

    @Override
    public AjaxResult analyzeDriverBehavior(DriverBehaviorRequest request) {
        try {
            // 1. 参数校验（图片、方向盘位置）
            validateRequest(request);
            log.info("驾驶行为分析：参数校验通过，图片Base64长度：{}字符", request.getBase64Image().length());

            // 2. 图片编码（复用手势识别的工具类：Base64 → URL编码）
            String encodedImage = BaiduAipUtil.encodeImageParam(request.getBase64Image());

            // 3. 构造百度API请求参数（含可选参数）
            StringBuilder paramBuilder = new StringBuilder("image=" + encodedImage);
            // 补充“识别类型”参数（若前端传递）
            if (StringUtils.hasText(request.getType())) {
                paramBuilder.append("&type=").append(request.getType());
                log.info("驾驶行为分析：指定识别类型：{}", request.getType());
            }
            // 补充“方向盘位置”参数（默认左舵车）
            String wheelLocation = StringUtils.hasText(request.getWheelLocation())
                    ? request.getWheelLocation() : defaultWheelLocation;
            paramBuilder.append("&wheel_location=").append(wheelLocation);
            log.info("驾驶行为分析：方向盘位置：{}（1=左舵，0=右舵）", wheelLocation);

            String requestParam = paramBuilder.toString();
            log.info("驾驶行为分析：请求参数（前100字符）：{}...",
                    requestParam.substring(0, Math.min(100, requestParam.length())));

            // 4. 获取有效access_token（复用手势识别的鉴权逻辑，自动缓存过期刷新）
            String accessToken = baiduAuthUtil.getValidAccessToken();
            log.info("驾驶行为分析：获取access_token（前20字符）：{}...",
                    accessToken.substring(0, Math.min(20, accessToken.length())));

            // 5. 构造百度API请求URL（access_token拼在URL后）
            String requestUrl = driverApiUrl + "?access_token=" + accessToken;

            // 6. 构造请求体（百度要求：application/x-www-form-urlencoded）
            MediaType formMediaType = MediaType.parse("application/x-www-form-urlencoded; charset=UTF-8");
            RequestBody requestBody = RequestBody.create(
                    formMediaType,
                    requestParam.getBytes(StandardCharsets.UTF_8)
            );

            // 7. 发送POST请求调用百度API
            Request baiduRequest = new Request.Builder()
                    .url(requestUrl)
                    .method("POST", requestBody)
                    .addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
                    .addHeader("Accept", "application/json")
                    .build();

            Response response = httpClient.newCall(baiduRequest).execute();
            String responseBody = response.body().string();
            log.info("驾驶行为分析：百度API响应：{}", responseBody);

            // 8. 校验HTTP状态（非200直接抛异常）
            if (!response.isSuccessful()) {
                throw new IOException("百度API请求失败，状态码：" + response.code() + "，响应：" + responseBody);
            }

            // 9. 解析响应（转换为自定义VO）
            DriverBehaviorResponse result = parseBaiduResponse(responseBody);

            return AjaxResult.success("驾驶行为分析成功", result);
        } catch (IllegalArgumentException e) {
            // 参数错误（如图片为空、大小超限）
            log.warn("驾驶行为分析：参数错误：{}", e.getMessage());
            return AjaxResult.error("参数错误：" + e.getMessage());
        } catch (JSONException e) {
            // JSON解析错误（百度响应格式异常）
            log.error("驾驶行为分析：响应解析失败", e);
            return AjaxResult.error("分析结果解析失败：" + e.getMessage());
        } catch (Exception e) {
            // 其他异常（鉴权失败、网络错误）
            log.error("驾驶行为分析：流程异常", e);
            return AjaxResult.error("分析失败：" + e.getMessage());
        }
    }

    /**
     * 校验请求参数合法性
     */
    private void validateRequest(DriverBehaviorRequest request) {
        // 校验图片非空
        if (!StringUtils.hasText(request.getBase64Image())) {
            throw new IllegalArgumentException("图片Base64编码不能为空，请重新上传");
        }

        // 校验图片大小（Base64转字节数：(长度*3)/4 - 填充符数量）
        long imageSize = (request.getBase64Image().length() * 3L) / 4 - countBase64Padding(request.getBase64Image());
        if (imageSize > maxImageSize) {
            throw new IllegalArgumentException(String.format(
                    "图片大小超限（最大%dMB），当前%.2fMB",
                    maxImageSize / 1024 / 1024, imageSize / 1024.0 / 1024.0
            ));
        }

        // 校验方向盘位置（仅允许0或1）
        if (StringUtils.hasText(request.getWheelLocation())
                && !"0".equals(request.getWheelLocation())
                && !"1".equals(request.getWheelLocation())) {
            throw new IllegalArgumentException("方向盘位置仅支持0（右舵）或1（左舵）");
        }
    }

    /**
     * 统计Base64填充符（=）数量（用于计算真实图片大小）
     */
    private int countBase64Padding(String base64) {
        int count = 0;
        for (int i = base64.length() - 1; i >= 0; i--) {
            if (base64.charAt(i) == '=') count++;
            else break;
        }
        return count;
    }

    /**
     * 解析百度API响应（转换为自定义VO）
     */
    private DriverBehaviorResponse parseBaiduResponse(String responseBody) throws JSONException {
        JSONObject json = new JSONObject(responseBody);

        // 优先处理百度返回的错误（如参数无效）
        if (json.has("error")) {
            String errorMsg = json.optString("error_description", "未知错误");
            throw new JSONException("百度API错误：" + errorMsg);
        }

        // 解析核心字段
        DriverBehaviorResponse result = new DriverBehaviorResponse();
        result.setLogId(json.getLong("log_id"));
        result.setPersonNum(json.getInt("person_num"));
        result.setDriverNum(json.optInt("driver_num", 0));

        // 解析驾驶员详细信息
        JSONArray personArray = json.getJSONArray("person_info");
        List<DriverBehaviorResponse.PersonInfo> personInfoList = new ArrayList<>();
        for (int i = 0; i < personArray.length(); i++) {
            JSONObject personObj = personArray.getJSONObject(i);
            DriverBehaviorResponse.PersonInfo personInfo = new DriverBehaviorResponse.PersonInfo();

            // 解析位置信息
            if (personObj.has("location")) {
                JSONObject locationObj = personObj.getJSONObject("location");
                DriverBehaviorResponse.Location location = new DriverBehaviorResponse.Location();
                location.setLeft(locationObj.getInt("left"));
                location.setTop(locationObj.getInt("top"));
                location.setWidth(locationObj.getInt("width"));
                location.setHeight(locationObj.getInt("height"));
                location.setScore((float) locationObj.getDouble("score"));
                personInfo.setLocation(location);
            }

            // 解析9种驾驶行为属性
            if (personObj.has("attributes")) {
                JSONObject attributesObj = personObj.getJSONObject("attributes");
                DriverBehaviorResponse.Attributes attributes = new DriverBehaviorResponse.Attributes();
                // 逐个解析行为（含概率和阈值）
                attributes.setSmoke(parseBehavior(attributesObj, "smoke"));
                attributes.setCellphone(parseBehavior(attributesObj, "cellphone"));
                attributes.setNotBucklingUp(parseBehavior(attributesObj, "not_buckling_up"));
                attributes.setBothHandsLeavingWheel(parseBehavior(attributesObj, "both_hands_leaving_wheel"));
                attributes.setNotFacingFront(parseBehavior(attributesObj, "not_facing_front"));
                attributes.setNoFaceMask(parseBehavior(attributesObj, "no_face_mask"));
                attributes.setYawning(parseBehavior(attributesObj, "yawning"));
                attributes.setEyesClosed(parseBehavior(attributesObj, "eyes_closed"));
                attributes.setHeadLowered(parseBehavior(attributesObj, "head_lowered"));
                personInfo.setAttributes(attributes);
            }

            personInfoList.add(personInfo);
        }
        result.setPersonInfo(personInfoList);

        return result;
    }

    /**
     * 解析单个驾驶行为（概率+阈值）
     */
    private DriverBehaviorResponse.Behavior parseBehavior(JSONObject attributesObj, String behaviorKey) {
        if (attributesObj.has(behaviorKey)) {
            JSONObject behaviorObj = attributesObj.getJSONObject(behaviorKey);
            DriverBehaviorResponse.Behavior behavior = new DriverBehaviorResponse.Behavior();
            behavior.setScore((float) behaviorObj.getDouble("score"));
            behavior.setThreshold((float) behaviorObj.getDouble("threshold"));
            return behavior;
        }
        return null;
    }
}
